import { useReducer } from 'react';
import Axios from 'axios'

const initialState = { status: 0, statusText: 'initialize', loading: false, data: null };

function reducer(state, action) {
    let options = {
        'success': { ...state, status: 1, statusText: 'success', loading: false, data: action.payload },
        'loading': { ...state, status: 2, statusText: 'loading', loading: true, },
        'error': { ...state, status: 3, statusText: 'error', loading: false },
        'finally': { ...state, loading: false },
    }
    let s = options[action.type];
    return s ? s : new Error();
}

/**
 * @name 自定义请求hook封装
 * @description 自定义请求hook, 传入请求方法, 返回请求的状态、接口返回数据和中断请求的方法
 * @param {*} fn 请求方法, 一个promise请求方法
 * @param {*} initData 初始值, 设定data的初始值, 默认为null
 */
function useRequest(fn, initData = null) {
    const [state, dispatch] = useReducer(reducer, { ...initialState, data: initData });
    const { token, cancel } = Axios.CancelToken.source();
    const request = (params, option) => {
        dispatch({ type: 'loading' })
        return new Promise((resolve, reject) => (
            fn(params, { ...option, cancelToken: token })
                .then(res => {
                    dispatch({ type: 'success', payload: res })
                    resolve(res);
                })
                .catch(err => {
                    dispatch({ type: 'error' })
                    reject(err)
                })
                .finally(() => {
                    dispatch({ type: 'finally' })
                })
        ))
    }

    return {
        status: state.status, // 请求状态
        statusText: state.statusText, // 请求状态描述
        loading: state.loading, // 加载状态
        data: state.data, // 初始数据或接口返回数据
        request, // 请求方法
        cancel, // 取消请求方法
    }
}

export default useRequest;